package com.chatplus.application.config.pay;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.chatplus.application.client.pay.AliPayClient;
import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.List;

/**
 * 支付配置
 */
@Configuration
@EnableScheduling
@EnableConfigurationProperties
@EnableFeignClients(basePackages = "com.chatplus.application")
@EnableAspectJAutoProxy()
public class PayConfig {

    private static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(PayConfig.class);


    public static final String CONFIG_KEY_ROOTS = "chatplus.pay";

    @Bean
    @ConfigurationProperties(CONFIG_KEY_ROOTS)
    public Properties appProperties() {
        return new Properties();
    }

    @Bean
    @ConfigurationProperties(CONFIG_KEY_ROOTS + ".alipay")
    public AliPayProperties aliPayProperties() {
        return new AliPayProperties();
    }

    @Bean
    @ConfigurationProperties(CONFIG_KEY_ROOTS + ".wechat")
    public WechatPayProperties wechatPayProperties() {
        return new WechatPayProperties();
    }

    @Bean
    public WxPayService wxPayContextService(PayConfig.WechatPayProperties wechatConfig) {
        WxPayService wxPayService = new WxPayServiceImpl();
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(wechatConfig.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(wechatConfig.getMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(wechatConfig.getMchKey()));
        payConfig.setNotifyUrl(StringUtils.trimToNull(wechatConfig.getNotifyUrl()));
        payConfig.setApiV3Key(StringUtils.trimToNull(wechatConfig.getApiV3Key()));
        payConfig.setPrivateKeyPath(StringUtils.trimToNull(wechatConfig.getPrivateKeyPath()));
        payConfig.setPrivateCertPath(StringUtils.trimToNull(wechatConfig.getPrivateCertPath()));
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }
    @Bean
    public Config getOptions(PayConfig.AliPayProperties aliPayConfig) {
        Config config = new Config();
        config.appId = aliPayConfig.getAppId();
        config.protocol = aliPayConfig.getProtocol();
        config.gatewayHost = aliPayConfig.getGatewayHost();
        config.signType = aliPayConfig.getSignType();
        config.alipayPublicKey = aliPayConfig.getAlipayPublicKey();
        config.merchantPrivateKey = aliPayConfig.getAppPrivateKey();
        // 转账等操作需要公钥证书
        config.merchantCertPath = aliPayConfig.getAppCertPath();
        config.alipayCertPath = aliPayConfig.getAlipayCertPath();
        config.alipayRootCertPath = aliPayConfig.getAlipayRootCertPath();
        // 3参数可选
        config.notifyUrl = aliPayConfig.getNotifyUrl();
        config.encryptKey = aliPayConfig.getEncryptKey();
        config.signProvider = aliPayConfig.getSignProvider();
        Factory.setOptions(config);
        return config;
    }

    public static class Properties {

        private Long maxPayMoney = Long.MAX_VALUE;

        public Long getMaxPayMoney() {
            return maxPayMoney;
        }

        public void setMaxPayMoney(Long maxPayMoney) {
            this.maxPayMoney = maxPayMoney;
        }
    }

    /**
     * WeChat 配置
     */
    public static class WechatPayProperties {
        private boolean enable = false;
        /**
         * 账号适用于那个终端付款如：APP，PC
         */
        private String useFor;
        /**
         * 设置微信公众号或者小程序等的appid
         */
        private String appId;

        /**
         * 微信支付商户号
         */
        private String mchId;

        /**
         * 微信支付商户密钥
         */
        private String mchKey;

        private String apiV3Key;

        /**
         * apiclient_key.p12文件的绝对路径，或者如果放在项目中，请以classpath:开头指定
         */
        private String privateKeyPath;
        /**
         * apiclient_cert.p12文件的绝对路径，或者如果放在项目中，请以classpath:开头指定
         */
        private String privateCertPath;

        /**
         * 业务回调地址
         */
        private String notifyUrl;

        /**
         * 是否进行分账
         */
        private boolean profitSharing;

        /**
         * 分账接收账号
         */
        private String subAccount;

        /**
         * 分账比率
         */
        private String proportion;

        /**
         * 手续费
         */
        private String poundageRate;

        public String getUseFor() {
            return useFor;
        }

        public void setUseFor(String useFor) {
            this.useFor = useFor;
        }

        public String getAppId() {
            return appId;
        }

        public void setAppId(String appId) {
            this.appId = appId;
        }

        public String getMchId() {
            return mchId;
        }

        public void setMchId(String mchId) {
            this.mchId = mchId;
        }

        public String getMchKey() {
            return mchKey;
        }

        public void setMchKey(String mchKey) {
            this.mchKey = mchKey;
        }

        public String getNotifyUrl() {
            return notifyUrl;
        }

        public void setNotifyUrl(String notifyUrl) {
            this.notifyUrl = notifyUrl;
        }

        public boolean getProfitSharing() {
            return profitSharing;
        }

        public void setProfitSharing(boolean profitSharing) {
            this.profitSharing = profitSharing;
        }

        public String getSubAccount() {
            return subAccount;
        }

        public void setSubAccount(String subAccount) {
            this.subAccount = subAccount;
        }

        public String getProportion() {
            return proportion;
        }

        public void setProportion(String proportion) {
            this.proportion = proportion;
        }

        public String getPoundageRate() {
            return poundageRate;
        }

        public void setPoundageRate(String poundageRate) {
            this.poundageRate = poundageRate;
        }

        public String getApiV3Key() {
            return apiV3Key;
        }

        public void setApiV3Key(String apiV3Key) {
            this.apiV3Key = apiV3Key;
        }

        public String getPrivateKeyPath() {
            return privateKeyPath;
        }

        public void setPrivateKeyPath(String privateKeyPath) {
            this.privateKeyPath = privateKeyPath;
        }

        public String getPrivateCertPath() {
            return privateCertPath;
        }

        public void setPrivateCertPath(String privateCertPath) {
            this.privateCertPath = privateCertPath;
        }

        public boolean isEnable() {
            return enable;
        }

        public void setEnable(boolean enable) {
            this.enable = enable;
        }
    }

    /**
     * Alipay 配置
     */
    public static class AliPayProperties {


        private boolean enable = false;
        /**
         * 通信协议，通常填写https
         */
        private String protocol = "https";

        /**
         * 网关域名
         * 线上为：openapi.alipay.com
         * 沙箱为：openapi.alipaydev.com
         */
        private String gatewayHost = "openapi.alipay.com";

        /**
         * AppId
         */
        private String appId;

        /**
         * 签名类型，Alipay Easy SDK只推荐使用RSA2，估此处固定填写RSA2
         */
        private String signType = "RSA2";

        /**
         * 支付宝公钥
         */
        private String alipayPublicKey;

        /**
         * 应用私钥
         */
        private String appPrivateKey;

        /**
         * 应用公钥证书文件路径
         */
        private String appCertPath;

        /**
         * 支付宝公钥证书文件路径
         */
        private String alipayCertPath;

        /**
         * 支付宝根证书文件路径
         */
        private String alipayRootCertPath;

        /**
         * 异步通知回调地址（可选）
         */
        private String notifyUrl;

        /**
         * AES密钥（可选）
         */
        private String encryptKey;

        /**
         * 签名提供方的名称(可选)，例：Aliyun KMS签名，signProvider = "AliyunKMS"
         */
        private String signProvider;

        /**
         * 支付宝授权地址
         */
        private String authorizeUrl = "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm";

        /**
         * 授权回调
         */
        private String authorizeCallback;

        /**
         * 签约的支付宝账号对应的支付宝唯一用户号，以 2088 开头的 16 位纯数字组成。
         */
        private String pid;

        /**
         * 是否支持沙箱环境(注: 正式环境不用配置,默认即可)
         */
        private boolean supportSandbox = true;

        public String getProtocol() {
            return protocol;
        }

        public void setProtocol(String protocol) {
            this.protocol = protocol;
        }

        public String getGatewayHost() {
            return gatewayHost;
        }

        public void setGatewayHost(String gatewayHost) {
            this.gatewayHost = gatewayHost;
        }

        public String getAppId() {
            return appId;
        }

        public void setAppId(String appId) {
            this.appId = appId;
        }

        public String getSignType() {
            return signType;
        }

        public void setSignType(String signType) {
            this.signType = signType;
        }

        public String getAlipayPublicKey() {
            return alipayPublicKey;
        }

        public void setAlipayPublicKey(String alipayPublicKey) {
            this.alipayPublicKey = alipayPublicKey;
        }

        public String getAppPrivateKey() {
            return appPrivateKey;
        }

        public void setAppPrivateKey(String appPrivateKey) {
            this.appPrivateKey = appPrivateKey;
        }

        public String getAppCertPath() {
            return appCertPath;
        }

        public void setAppCertPath(String appCertPath) {
            this.appCertPath = appCertPath;
        }

        public String getAlipayCertPath() {
            return alipayCertPath;
        }

        public void setAlipayCertPath(String alipayCertPath) {
            this.alipayCertPath = alipayCertPath;
        }

        public String getAlipayRootCertPath() {
            return alipayRootCertPath;
        }

        public void setAlipayRootCertPath(String alipayRootCertPath) {
            this.alipayRootCertPath = alipayRootCertPath;
        }

        public String getNotifyUrl() {
            return notifyUrl;
        }

        public void setNotifyUrl(String notifyUrl) {
            this.notifyUrl = notifyUrl;
        }

        public String getEncryptKey() {
            return encryptKey;
        }

        public void setEncryptKey(String encryptKey) {
            this.encryptKey = encryptKey;
        }

        public String getSignProvider() {
            return signProvider;
        }

        public void setSignProvider(String signProvider) {
            this.signProvider = signProvider;
        }

        public String getAuthorizeUrl() {
            return authorizeUrl;
        }

        public void setAuthorizeUrl(String authorizeUrl) {
            this.authorizeUrl = authorizeUrl;
        }

        public String getAuthorizeCallback() {
            return authorizeCallback;
        }

        public void setAuthorizeCallback(String authorizeCallback) {
            this.authorizeCallback = authorizeCallback;
        }

        public String getPid() {
            return pid;
        }

        public void setPid(String pid) {
            this.pid = pid;
        }

        public boolean isSupportSandbox() {
            return supportSandbox;
        }

        public void setSupportSandbox(boolean supportSandbox) {
            this.supportSandbox = supportSandbox;
        }

        public boolean isEnable() {
            return enable;
        }

        public void setEnable(boolean enable) {
            this.enable = enable;
        }
    }
}
